class Vue{
    constructor(options){
        this.$options = options;
        this.initData()
    }
    initData(){
        let data = this._data = this.$options.data;
        let keys = Object.keys(data)

        for(let i=0;i<keys.length;i++){
            Object.defineProperty(this,keys[i],{
                enumerable: true,
                configurable: true,
                get: function proxyGetter(){
                    return this._data[keys[i]]
                },
                set: function proxySetter(val){
                    this._data[keys[i]] = val
                }
            })
        }

        observe(data)
    }
}

function observe(data){
    let type = Object.prototype.toString.call(data)
    if(type !== '[object Object]' && type !== '[object Array]') return
    new Observer(data)
}

function defineReactive(obj,key,val){
    // 如果被观测的是对象，则递归
    observe(val)

    Object.defineProperty(obj,key,{
        enumerable: true,
        configurable: true,
        get: function reactiveGetter(){
            return val
        },
        set: function reactiveSetter(newval){
            val = newval
        }
    })
}

class Observer{
    constructor(data){
        this.walk(data)
    }
    walk(data){
        let keys = Object.keys(data)
        for(let i = 0;i<keys.length;i++){
            defineReactive(data,keys[i],data[keys[i]])
        }
    }
}
